package org.iku.crawl.handler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.MatchResult;

import org.apache.commons.beanutils.BeanUtils;
import org.heydr.annotation.HandleInfo;
import org.heydr.common.TaskEngine;
import org.heydr.common.http.StringUtils;
import org.heydr.entity.Page;
import org.heydr.entity.Url;
import org.heydr.handler.impl.SubHandler;
import org.heydr.impl.SubCrawler;
import org.iku.common.ActressTool;
import org.iku.common.CategoryTool;
import org.iku.common.RegexTool;
import org.iku.crawl.dao.ResourceDAO;
import org.iku.entity.Actress;
import org.iku.entity.Category;
import org.iku.entity.Item;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

@Component
public class JAVIMDBInfoHandler extends SubHandler{
	private static Logger logger = LoggerFactory.getLogger(JAVIMDBInfoHandler.class);
	
	@Autowired
	private ResourceDAO resourceDAO;
	
	@Async
	public void run(Url url, Object object) {
		try {
			Item item = handle(url, object);
			String md5 = StringUtils.md5(url.getUrl());
			item.setMd5(md5);
			int i = resourceDAO.addItem(item);
			if(i>0){
				TaskEngine.addSnatchedUrl(md5);
			}else{
				logger.info(url.getUrl()+" already snatched.");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public Item handle(Url url, Object object) {
		Item item = (Item)object;
		
		Page pageCn = SubCrawler.snatch(url);
		String contentCn = pageCn.getContent();
		Url urlEn = null;
		try {
			urlEn = (Url)BeanUtils.cloneBean(url);
		} catch (Exception e) {
			
		}
		urlEn.setUrl(urlEn.getUrl().replace("/cn/", "/en/"));
		Page pageEn = SubCrawler.snatch(urlEn);
		String contentEn = pageEn.getContent();
		String sn = RegexTool.singleExtract(contentCn, "识别码:.*>(.*?)</span>", 1);
		String sn_en = RegexTool.singleExtract(contentEn, "ID:.*>(.*?)</span>", 1);
		if(null != sn && null != sn_en){
			/* 中文详情页 */
			String cover = RegexTool.singleExtract(contentCn, "class=\"bigImage\" href=\"(.*?)\">", 1);
			String date = RegexTool.singleExtract(contentCn, "(\\d{4}-\\d{2}-\\d{2})", 1);
			String during = RegexTool.singleExtract(contentCn, "(\\d+)分钟", 1);
			String maker_cn = RegexTool.singleExtract(contentCn, "制作商:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String publisher_cn = RegexTool.singleExtract(contentCn, "发行商:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String series_cn = RegexTool.singleExtract(contentCn, "系列:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String director_cn = RegexTool.singleExtract(contentCn, "导演:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			
			List<MatchResult> matchCategoryCn = RegexTool.multiExtractToMatchResult(contentCn, "http://www\\.javimdb\\.com/cn/genre/(.*?)\">(.*?)<");
			
			/* 英文字段补全 */
			String maker_en = RegexTool.singleExtract(contentEn, "Studio:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String publisher_en = RegexTool.singleExtract(contentEn, "Label:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String series_en = RegexTool.singleExtract(contentEn, "Series:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			String director_en = RegexTool.singleExtract(contentEn, "Director:[\\s\\S]+?href=\".*?\">(.*?)<", 1);
			
			List<MatchResult> matchCategoryEn = RegexTool.multiExtractToMatchResult(contentEn, "http://www\\.javimdb\\.com/en/genre/(.*?)\">(.*?)<");			
			
			Document docCn = Jsoup.parse(contentCn);
			String actContent = docCn.select("div.star-box").html();
			List<MatchResult> actMatchs = RegexTool.multiExtractToMatchResult(actContent,"star-name[\\s\\S]+?<a href=\"(.*?)\">(.*?)<");
			String imgs = docCn.select("div.sample-box").html();
			List<MatchResult> imgMatchs = RegexTool.multiExtractToMatchResult(imgs, "<li>[\\s\\S]+?href=\"(.*?)\"><img src=\"(.*?)\"");
			//拼裝女優
			String actresses = combineActress(actMatchs);
			//拼裝類型
			String categories = combineCategory(matchCategoryCn,matchCategoryEn);
			//拼裝圖片
			String sampleFullImgs = combineImg(imgMatchs);
			
			item.setCategory(categories);
			item.setFullImage(cover);
			item.setPublishTime(date);
			item.setDuringTime(during);
			item.setMakerCn(maker_cn);
			item.setMakerEn(maker_en);
			item.setPublisherCn(publisher_cn);
			item.setPublisherEn(publisher_en);
			item.setSeriesCn(series_cn);
			item.setSeriesEn(series_en);
			item.setDirectorCn(director_cn);
			item.setDirectorEn(director_en);
			item.setSn(sn);
			item.setActressIds(actresses);
			item.setSampleImgs(sampleFullImgs);
			
		}
		return item;
	}
	
	public String combineCategory(List<MatchResult> matchsCn,List<MatchResult> matchsEn){
		List<Integer> temp = new ArrayList<Integer>();
		Map<String,String> cnMap = new HashMap<String,String>();
		
		for(MatchResult match : matchsCn){
			cnMap.put(match.group(1), match.group(2));
		}
		
		for(MatchResult match : matchsEn){
			String key = match.group(1);
			String value = match.group(2);
			Category category = new Category();
			if(!CategoryTool.containCategory(value)){
				//未收錄分類
				category.setNameEn(value);
				category.setNameCn(cnMap.get(key));
				category.setMd5(key);
				int i = resourceDAO.addCategory(category);
				if(i > 0){
					CategoryTool.addCategory(category);
				}else{
					category = CategoryTool.getCategory(value);
				}
			}else{
				category = CategoryTool.getCategory(value);
			}
			
			temp.add(category.getId());
		}
		
		Gson gson = new Gson();
		return gson.toJson(temp);
	}
	
	public String combineActress(List<MatchResult> matchsCn){
		List<Integer> temp = new ArrayList<Integer>();
//		Map<String,String> cnMap = new HashMap<String,String>();
		
//		for(MatchResult match : matchsCn){
//			cnMap.put(match.group(1), match.group(2));
//		}
		
		for(MatchResult match : matchsCn){
			String key = match.group(2);
			String value = match.group(1);
			String md5 = StringUtils.md5(value);
			Actress actress = new Actress();
			if(!ActressTool.containActress(key)){
				//未收錄分類
				Url url = new Url();
				value = value.replace("/cn/", "/en/");
				url.setUrl(value);
				actress = snatchActress(url);
				actress.setNameCn(key);
				actress.setMd5(md5);
				int i = resourceDAO.addActress(actress);
				if(i > 0){
					ActressTool.addActress(actress);
				}else{
					actress = ActressTool.getActress(key);
				}
			}else{
				actress = ActressTool.getActress(key);
			}
			
			temp.add(actress.getId());
		}
		Gson gson = new Gson();
		return gson.toJson(temp);
	}
	
	public Actress snatchActress(Url url){
		Page pageEn = SubCrawler.snatch(url);
		String contentEn = pageEn.getContent();
		contentEn = Jsoup.parse(contentEn).select("div.item:has(b)").html();
		String nameEn = RegexTool.singleExtract(contentEn, "<b>(.*)</b>", 1);
		String birthday = RegexTool.singleExtract(contentEn, "(\\d{4}-\\d{2}-\\d{2})", 1);
		String height = RegexTool.singleExtract(contentEn, "Height: (\\d+)", 1);
		String cup = RegexTool.singleExtract(contentEn, "Cup: (.*?)<", 1);
		String bust = RegexTool.singleExtract(contentEn, "Bust: (\\d+)", 1);
		String waist = RegexTool.singleExtract(contentEn, "Waist: (\\d+)", 1);
		String hips = RegexTool.singleExtract(contentEn, "Hips: (\\d+)", 1);
		String bornAddrCn = RegexTool.singleExtract(contentEn, "Hometown: (.*?)<", 1);
		String hobbyCn = RegexTool.singleExtract(contentEn, "Hobby: (.*?)<", 1);
		String coverImg = RegexTool.singleExtract(contentEn, "src=\"(.*?)\".*?class=\"star\"", 1);
		
//		url.setUrl(url.getUrl().replace("/cn/", "/en/"));
//		Page pageEn = SubCrawler.snatch(url);
//		String contentEn = pageEn.getContent();
		
		Actress actress = new Actress();
		actress.setNameEn(nameEn);
		actress.setBirthday(birthday);
		actress.setHeight(height);
		actress.setCup(cup);
		actress.setBust(bust);
		actress.setWaist(waist);
		actress.setHips(hips);
		actress.setBornAddrCn(bornAddrCn);
		actress.setHobbyCn(hobbyCn);
		actress.setCoverImg(coverImg);
		
		return actress;
	}
	
	public String combineImg(List<MatchResult> matchsCn){
		JsonObject jsonObject = new JsonObject();
		for(MatchResult match : matchsCn){
			jsonObject.addProperty(match.group(1), match.group(2));
		}
		Gson gson = new Gson();
		return gson.toJson(jsonObject);
	}
}
